﻿using System;
using System.Collections.Generic;
using System.Text;
using System.Xml;
using System.Windows.Forms;
using mEdit.Properties;

namespace mEdit.Controls
{
    partial class mTreeView
    {
        // ==== Load 
        public void Load(string fileName)
        {
            CheckAndSaveContent();

            this.Nodes.Clear();

            this._fileName = fileName;

            XmlDocument doc = new XmlDocument();
            doc.Load(fileName);

            foreach (XmlNode xmlRootNode in doc.ChildNodes)
            {
                if (xmlRootNode.Name != "Nodes")
                    continue;
                foreach (XmlNode node in xmlRootNode.ChildNodes)
                {
                    LoadNodeData(node, null);
                }
            }
            this.ExpandAll();
            // set default node
            if (this.Nodes.Count > 0)
                this.SelectedNode = this.Nodes[0];
        }

        private TreeNode LoadNodeData(XmlNode xmlNode, TreeNode parentNode)
        {
            TreeNode node = new TreeNode();
            node.Text = xmlNode.Attributes["Name"].Value;
            node.Tag = GetNodeData(xmlNode);

            if (parentNode == null)
                this.Nodes.Add(node);
            else
                parentNode.Nodes.Add(node);
            LoadInnerNodes(xmlNode, node);
            return node;
        }

        private void LoadInnerNodes(XmlNode xmlNode, TreeNode parentNode)
        {
            foreach (XmlNode n in xmlNode)
            {
                if (n.Name != "InnerNodes")
                    continue;
                foreach (XmlNode innerNode in n.ChildNodes)
                {
                    if (innerNode.Name == "Node")
                    {
                        TreeNode newNode = new TreeNode();
                        newNode.Text = innerNode.Attributes["Name"].Value;
                        newNode.Tag = GetNodeData(innerNode);
                        parentNode.Nodes.Add(newNode);
                        LoadInnerNodes(innerNode, newNode);
                    }
                }
            }
        }

        private string GetNodeData(XmlNode xmlNode)
        {
            foreach (XmlNode n in xmlNode.ChildNodes)
            {
                if (n.Name == "Content" && n.ChildNodes.Count > 0)
                    return n.ChildNodes[0].Value;
            }
            return string.Empty;
        }


        /// <summary>
        /// Saves content of the tree.
        /// Assumes, that content is to be saved to already open file.
        /// </summary>
        public void Save()
        {
            if (!GetFileName())
                return;

            if (this.Nodes.Count < 1)
                return;

            XmlTextWriter writer = new XmlTextWriter(_fileName, Encoding.UTF8);
            try
            {
                XmlDocument doc = new XmlDocument();
                doc.PreserveWhitespace = true;
                XmlDeclaration xmlDeclaration = doc.CreateXmlDeclaration("1.0", Encoding.UTF8.WebName, null);
                doc.AppendChild(xmlDeclaration);
                XmlNode xmlNodes = doc.CreateNode(XmlNodeType.Element, "Nodes", null);
                doc.AppendChild(xmlNodes);

                foreach (TreeNode mn in this.Nodes)
                {
                    SaveNode(doc, xmlNodes, mn);
                }

                writer.Formatting = Formatting.Indented;
                writer.Indentation = 4;
                doc.Save(writer);
                Settings.Default.LastOpenedFile = _fileName;
                Settings.Default.Save();
            }
            catch
            {
                MessageBox.Show("Error saving file!");
            }
            finally
            {
                writer.Close();
            }
        }

        private void SaveNode(XmlDocument doc, XmlNode parentNode, TreeNode node)
        {
            XmlNode newNode = doc.CreateNode(XmlNodeType.Element, "Node", string.Empty);
            XmlAttribute nodeName = doc.CreateAttribute("Name");
            nodeName.Value = node.Text;
            newNode.Attributes.Append(nodeName);

            XmlNode content = doc.CreateNode(XmlNodeType.Element, "Content", null);
            XmlNode cdata = doc.CreateNode(XmlNodeType.CDATA, "Content", string.Empty);
            cdata.Value = (node.Tag != null) ? node.Tag.ToString() : string.Empty;
            content.AppendChild(cdata);
            newNode.AppendChild(content);
            parentNode.AppendChild(newNode);

            if (node.Nodes.Count > 0)
            {
                XmlNode xmlNodes = doc.CreateNode(XmlNodeType.Element, "InnerNodes", null);
                newNode.AppendChild(xmlNodes);
                foreach (TreeNode n in node.Nodes)
                    SaveNode(doc, xmlNodes, n);
            }
        }

        /// <summary>
        /// Saves content of the tree to a specified file.
        /// </summary>
        /// <param name="fileName"></param>
        public void Save(string fileName)
        {
            this._fileName = fileName;
            this.Save();
        }

        // ==== end of: Load & Save
    }
}